#!/usr/bin/env python3
"""
简化的WVP客户端
用于从Java后端获取WVP设备和通道数据
"""
import aiohttp
import asyncio
import logging
from typing import Dict, List, Any, Optional
import json
from datetime import datetime, timedelta

logger = logging.getLogger(__name__)

class WVPAuthClient:
    """WVP认证客户端"""
    
    def __init__(self, base_url: str = "http://localhost:8080", username: str = "admin", password: str = "admin123", timeout: int = 30):
        self.base_url = base_url.rstrip('/')
        self.username = username
        self.password = password
        self.timeout = timeout
        self.session = None
        self.token = None
        self.token_expires = None
    
    async def __aenter__(self):
        """异步上下文管理器入口"""
        self.session = aiohttp.ClientSession(
            timeout=aiohttp.ClientTimeout(total=self.timeout),
            headers={
                "Content-Type": "application/json",
                "User-Agent": "Campus-Twin-Python-Backend/1.0"
            }
        )
        await self._login()
        return self
    
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        """异步上下文管理器出口"""
        if self.session:
            await self.session.close()
    
    async def _login(self) -> bool:
        """登录获取token"""
        try:
            login_data = {
                "username": self.username,
                "password": self.password
            }
            
            async with self.session.post(f"{self.base_url}/login", json=login_data) as response:
                if response.status == 200:
                    data = await response.json()
                    if data.get("code") == 200:
                        self.token = data.get("token")
                        self.token_expires = datetime.now() + timedelta(hours=24)
                        logger.info("WVP登录成功")
                        return True
                    else:
                        logger.error(f"WVP登录失败: {data.get('msg', '未知错误')}")
                        return False
                else:
                    logger.error(f"WVP登录HTTP错误: {response.status}")
                    return False
        except Exception as e:
            logger.error(f"WVP登录异常: {e}")
            return False
    
    async def _ensure_authenticated(self) -> bool:
        """确保已认证"""
        if not self.token or not self.token_expires:
            return await self._login()
        
        if datetime.now() >= self.token_expires - timedelta(minutes=5):
            return await self._login()
        
        return True
    
    def _get_headers(self) -> Dict[str, str]:
        """获取请求头"""
        headers = {
            "Content-Type": "application/json",
            "Accept": "application/json"
        }
        if self.token:
            headers["Authorization"] = f"Bearer {self.token}"
        return headers
    
    async def _make_request(self, method: str, url: str, **kwargs) -> Dict[str, Any]:
        """发起认证请求"""
        if not await self._ensure_authenticated():
            raise Exception("WVP认证失败")
        
        headers = self._get_headers()
        
        try:
            async with self.session.request(method, f"{self.base_url}{url}", headers=headers, **kwargs) as response:
                if response.status == 401:
                    logger.warning("WVP token可能已过期，尝试重新登录")
                    if await self._login():
                        headers = self._get_headers()
                        async with self.session.request(method, f"{self.base_url}{url}", headers=headers, **kwargs) as retry_response:
                            if retry_response.status == 200:
                                return await retry_response.json()
                            else:
                                raise Exception(f"WVP请求失败: {retry_response.status}")
                    else:
                        raise Exception("WVP重新认证失败")
                elif response.status == 200:
                    return await response.json()
                else:
                    raise Exception(f"WVP请求失败: {response.status}")
        except Exception as e:
            logger.error(f"WVP请求异常: {e}")
            raise
    
    async def get_devices(self, page: int = 1, count: int = 50, **kwargs) -> Dict[str, Any]:
        """获取设备列表"""
        try:
            params = {
                "pageNum": page,
                "pageSize": count,
                **kwargs
            }
            
            data = await self._make_request("GET", "/api/device/query/devices", params=params)
            logger.info(f"获取设备列表成功，共 {data.get('total', 0)} 个设备")
            return data
            
        except Exception as e:
            logger.error(f"获取设备列表失败: {e}")
            raise
    
    async def get_device_channels(self, device_id: str = None, page: int = 1, count: int = 50, **kwargs) -> Dict[str, Any]:
        """获取设备通道列表"""
        try:
            params = {
                "pageNum": page,
                "pageSize": count,
                **kwargs
            }
            
            if device_id:
                params["deviceId"] = device_id
            
            data = await self._make_request("GET", "/api/device/query/devices/channels", params=params)
            logger.info(f"获取设备通道列表成功，共 {data.get('total', 0)} 个通道")
            return data
            
        except Exception as e:
            logger.error(f"获取设备通道列表失败: {e}")
            raise
    
    async def get_play_url(self, device_id: str, channel_id: str) -> Dict[str, Any]:
        """获取播放URL"""
        try:
            url = f"/api/play/start/{device_id}/{channel_id}"
            data = await self._make_request("GET", url)
            logger.info(f"获取播放URL成功: {device_id}/{channel_id}")
            return data
            
        except Exception as e:
            logger.error(f"获取播放URL失败: {e}")
            raise
    
    async def stop_play(self, device_id: str, channel_id: str) -> Dict[str, Any]:
        """停止播放"""
        try:
            url = f"/api/play/stop/{device_id}/{channel_id}"
            data = await self._make_request("GET", url)
            logger.info(f"停止播放成功: {device_id}/{channel_id}")
            return data
            
        except Exception as e:
            logger.error(f"停止播放失败: {e}")
            raise


class WVPSyncService:
    """WVP数据同步服务"""
    
    def __init__(self, wvp_base_url: str = "http://localhost:8080"):
        self.wvp_base_url = wvp_base_url
        self.wvp_username = "admin"
        self.wvp_password = "admin123"
    
    async def sync_devices_and_channels(self, db_manager) -> Dict[str, Any]:
        """同步设备和通道数据"""
        try:
            async with WVPAuthClient(self.wvp_base_url, self.wvp_username, self.wvp_password) as client:
                # 获取所有设备
                devices_data = await client.get_devices(page=1, count=1000)
                devices = devices_data.get("rows", [])
                
                synced_devices = 0
                synced_channels = 0
                
                for device in devices:
                    device_id = device.get("deviceId")
                    if not device_id:
                        continue
                    
                    # 同步设备信息到WVP设备表
                    device_data = {
                        "device_id": device_id,
                        "device_name": device.get("name", f"设备-{device_id}"),
                        "manufacturer": device.get("manufacturer", ""),
                        "model": device.get("model", ""),
                        "ip": device.get("ip", ""),
                        "port": device.get("port", 5060),
                        "status": "online" if device.get("online") else "offline",
                        "register_time": datetime.now(),
                        "keepalive_time": datetime.now() if device.get("online") else None
                    }
                    
                    # 插入或更新设备
                    try:
                        # 检查设备是否存在
                        query = "SELECT id FROM wvp_devices WHERE device_id = ?"
                        existing = db_manager.execute_query(query, (device_id,))
                        
                        if existing:
                            # 更新设备
                            update_query = """
                                UPDATE wvp_devices SET 
                                    device_name = ?, manufacturer = ?, model = ?, ip = ?, port = ?,
                                    status = ?, keepalive_time = ?, updated_at = CURRENT_TIMESTAMP
                                WHERE device_id = ?
                            """
                            db_manager.execute_update(update_query, (
                                device_data["device_name"], device_data["manufacturer"], 
                                device_data["model"], device_data["ip"], device_data["port"],
                                device_data["status"], device_data["keepalive_time"], device_id
                            ))
                        else:
                            # 插入新设备
                            insert_query = """
                                INSERT INTO wvp_devices (
                                    device_id, device_name, manufacturer, model, ip, port,
                                    status, register_time, keepalive_time, created_at
                                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
                            """
                            db_manager.execute_insert(insert_query, (
                                device_id, device_data["device_name"], device_data["manufacturer"],
                                device_data["model"], device_data["ip"], device_data["port"],
                                device_data["status"], device_data["register_time"], 
                                device_data["keepalive_time"]
                            ))
                            synced_devices += 1
                    
                    except Exception as e:
                        logger.error(f"同步设备 {device_id} 失败: {e}")
                        continue
                    
                    # 获取并同步设备通道 - 关键：通道就是摄像头！
                    try:
                        channels_data = await client.get_device_channels(device_id, page=1, count=1000)
                        channels = channels_data.get("rows", [])
                        
                        for channel in channels:
                            channel_id = channel.get("channelId") or channel.get("deviceId")
                            if not channel_id:
                                continue
                            
                            # 1. 同步到WVP通道表
                            channel_data = {
                                "device_id": device_id,
                                "channel_id": channel_id,
                                "channel_name": channel.get("name", f"通道-{channel_id}"),
                                "status": "online" if channel.get("status") == "ON" else "offline",
                                "longitude": channel.get("longitude"),
                                "latitude": channel.get("latitude"),
                                "address": channel.get("address", "")
                            }
                            
                            # 检查通道是否存在
                            query = "SELECT id FROM wvp_channels WHERE device_id = ? AND channel_id = ?"
                            existing = db_manager.execute_query(query, (device_id, channel_id))
                            
                            if existing:
                                # 更新通道
                                update_query = """
                                    UPDATE wvp_channels SET 
                                        channel_name = ?, status = ?, longitude = ?, latitude = ?,
                                        address = ?, updated_at = CURRENT_TIMESTAMP
                                    WHERE device_id = ? AND channel_id = ?
                                """
                                db_manager.execute_update(update_query, (
                                    channel_data["channel_name"], channel_data["status"],
                                    channel_data["longitude"], channel_data["latitude"],
                                    channel_data["address"], device_id, channel_id
                                ))
                            else:
                                # 插入新通道
                                insert_query = """
                                    INSERT INTO wvp_channels (
                                        device_id, channel_id, channel_name, status, 
                                        longitude, latitude, address, created_at
                                    ) VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
                                """
                                db_manager.execute_insert(insert_query, (
                                    device_id, channel_id, channel_data["channel_name"],
                                    channel_data["status"], channel_data["longitude"],
                                    channel_data["latitude"], channel_data["address"]
                                ))
                                synced_channels += 1
                            
                            # 2. 关键：将通道同步为摄像头！
                            camera_data = {
                                "camera_id": channel_id,  # 使用通道ID作为摄像头ID
                                "name": channel.get("name", f"摄像头-{channel_id}"),
                                "location": channel.get("address", "未知位置"),
                                "status": "online" if channel.get("status") == "ON" else "offline",
                                "ai_enabled": False,  # 默认关闭AI
                                "ai_algorithms": "[]",
                                "device_id": device_id,  # 关联到WVP设备
                                "longitude": channel.get("longitude"),
                                "latitude": channel.get("latitude"),
                                "resolution": "1920x1080",  # 默认分辨率
                                "fps": 25  # 默认帧率
                            }
                            
                            # 检查摄像头是否存在
                            camera_query = "SELECT id FROM cameras WHERE camera_id = ?"
                            existing_camera = db_manager.execute_query(camera_query, (channel_id,))
                            
                            if existing_camera:
                                # 更新摄像头
                                update_camera_query = """
                                    UPDATE cameras SET 
                                        name = ?, location = ?, status = ?, device_id = ?,
                                        longitude = ?, latitude = ?, updated_at = CURRENT_TIMESTAMP
                                    WHERE camera_id = ?
                                """
                                db_manager.execute_update(update_camera_query, (
                                    camera_data["name"], camera_data["location"], camera_data["status"],
                                    camera_data["device_id"], camera_data["longitude"], 
                                    camera_data["latitude"], channel_id
                                ))
                            else:
                                # 插入新摄像头
                                insert_camera_query = """
                                    INSERT INTO cameras (
                                        camera_id, name, location, status, ai_enabled, ai_algorithms,
                                        device_id, longitude, latitude, resolution, fps, created_at
                                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
                                """
                                db_manager.execute_insert(insert_camera_query, (
                                    camera_data["camera_id"], camera_data["name"], camera_data["location"],
                                    camera_data["status"], camera_data["ai_enabled"], camera_data["ai_algorithms"],
                                    camera_data["device_id"], camera_data["longitude"], camera_data["latitude"],
                                    camera_data["resolution"], camera_data["fps"]
                                ))
                    
                    except Exception as e:
                        logger.error(f"同步设备 {device_id} 的通道失败: {e}")
                        continue
                
                return {
                    "success": True,
                    "synced_devices": synced_devices,
                    "synced_channels": synced_channels,
                    "total_devices": len(devices),
                    "message": f"同步完成: {synced_devices} 个设备, {synced_channels} 个通道"
                }
        
        except Exception as e:
            logger.error(f"WVP数据同步失败: {e}")
            return {
                "success": False,
                "error": str(e),
                "message": f"同步失败: {str(e)}"
            }


# 全局同步服务实例
wvp_sync_service = WVPSyncService()


def get_wvp_sync_service() -> WVPSyncService:
    """获取WVP同步服务实例"""
    return wvp_sync_service


def get_wvp_auth_client(base_url: str = "http://localhost:8080", username: str = "admin", password: str = "admin123") -> WVPAuthClient:
    """获取WVP认证客户端实例"""
    return WVPAuthClient(base_url, username, password)